package com.hibegin.ftp;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class FtpNIOClient {
    private SocketChannel client;
    private SelectionKey selectionKey;
    private Selector selector;
    private FtpSession ftpSession;
    private FtpLoginSuccessCallBack callBack;
    private FtpUser ftpUser;

    public FtpNIOClient(FtpLoginSuccessCallBack callBack, FtpUser ftpUser) {
        super();
        this.callBack = callBack;
        this.ftpUser = ftpUser;
    }

    public FtpNIOClient() {
        super();
    }


    public void connectServer() {
        InetSocketAddress SERVER_ADDRESS = new InetSocketAddress(
                ftpUser.getAddr(), ftpUser.getPort());
        try {
            // 打开socket通道
            SocketChannel socketChannel = SocketChannel.open();
            // 设置为非阻塞方式
            socketChannel.configureBlocking(false);
            // 打开选择器
            selector = Selector.open();
            Iterator iterator;
            Set<SelectionKey> selectionKeys;
            // 注册连接服务端socket动作
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            // 连接
            socketChannel.connect(SERVER_ADDRESS);
            // 分配缓冲区大小内存
            while (true) {
                // 选择一组键，其相应的通道已为 I/O 操作准备就绪。
                // 此方法执行处于阻塞模式的选择操作。
                selector.select();
                // 返回此选择器的已选择键集。
                selectionKeys = selector.selectedKeys();
                iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    selectionKey = (SelectionKey) iterator.next();
                    client = (SocketChannel) selectionKey.channel();
                    if (selectionKey.isConnectable()) {
                        if (client.isConnectionPending()) {
                            client.finishConnect();
                            ftpSession = new FtpSession(ftpUser, this);
                            if (callBack != null) {
                                ftpSession.getAttr().put("callBack", callBack);
                            }
                            System.out.println("connect finished");
                        }
                        client.register(selector, SelectionKey.OP_READ);
                    } else if (selectionKey.isReadable()) {
                        ByteBuffer input = ByteBuffer.allocate(1024 * 100);
                        client.read(input);
                        input.flip();
                        String strArr[] = new String(input.array()).trim()
                                .split("\r\n");
                        for (String string : strArr) {
                            System.out.println("resp --< " + string);
                        }
                        for (String string : strArr) {
                            ftpSession.readMsg(string);
                        }
                    } else if (selectionKey.isWritable()) {
                        ftpSession.sendMsg(selectionKey.attachment().toString());
                    }
                }
                selectionKeys.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public SocketChannel getClient() {
        return client;
    }

    public SelectionKey getSelectionKey() {
        return selectionKey;
    }

    public Selector getSelector() {
        return selector;
    }

    public FtpSession getFtpSession() {
        return ftpSession;
    }


}